﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using DotNetNuke.Entities.Tabs;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Security.Permissions;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Services.Localization;
using System.Data;
using iLangl.Customer.DNN.Entities;
using iLangl.Model;
using System.Text;
using DotNetNuke.Entities.Content;
using DotNetNuke.Framework;
using System.Xml;
using DotNetNuke.Entities.Users;

namespace iLangl.Customer.DNN
{
	public class ContentManager
	{
		public static dtoContent.ContentRow Find(dtoContent content, String contenttype, String local, int ContentId)
		{
			foreach (dtoContent.ContentRow cr in content.Content)
			{
				if ((cr.ContentId == ContentId) && (cr.ContentType == contenttype) && (cr.CultureCode == local))
				{
					return cr;
				}
			}
			return null;

		}
		
		#region Singelton Pattern
		private static ContentManager instance;
		private static object mutex = new object();
		/// <summary>
		/// The instance of the ProjectManager.
		/// </summary>
		public static ContentManager Instance
		{
			get
			{
				if (instance == null)
				{
					lock (mutex)
					{
						if (instance == null)
						{
							instance = new ContentManager();

						}
					}
				}
				return instance;
			}
		}
		#endregion

		public const String TabType = "tab";
		public const String ModuleType = "module";

		public ContentPresenter GetContent(int portalId, string sourcecultureCode, string targetcultureCode)
		{
			dtoContent content = new dtoContent();
			return getContent(portalId, sourcecultureCode, targetcultureCode, content);
		}

		public ContentPresenter GetContent(int portalId, string sourcecultureCode, string targetcultureCode, dtoContent content)
		{
			return getContent(portalId, sourcecultureCode, targetcultureCode, content);
		}

		private List<ModuleInfo> GetChildModules(int portalId, int tabId, Locale locale)
		{
			var modules = new List<ModuleInfo>();
			var tabCtrl = new TabController();
			
			if (locale != null)
			{
				modules = (from kvp in tabCtrl.GetTabByCulture(tabId, portalId, locale).ChildModules where !kvp.Value.IsDeleted select kvp.Value).ToList();
			}
			return modules;
		}

		private ContentPresenter getContent(int portalId, string sourcecultureCode, string targetcultureCode, dtoContent content)
		{

			ContentPresenter result = new ContentPresenter(content);
			result.CultureCode = sourcecultureCode;

			Locale source = LocaleController.Instance.GetLocale(sourcecultureCode);
			Locale target = LocaleController.Instance.GetLocale(targetcultureCode);

			bool isParentFound = false;

			List<TabInfo> tabs = TabController.GetPortalTabs(portalId, Null.NullInteger, false, true, false, true);

			var tabCtrl = new TabController();

			foreach (var gtab in tabs)
			{
				if (TabPermissionController.CanViewPage(gtab))
				{
					TabInfo tab = tabCtrl.GetTabByCulture(gtab.TabID, portalId, source);
					dtoContent.ContentRow tabRow = Find(content, TabType, source.LanguageId.ToString(), tab.TabID);
					bool isnew = tabRow == null;
						
					if(isnew)
						tabRow = content.Content.NewContentRow();

					tabRow.ContentId = tab.TabID;
					tabRow.Title = GetContentName(tab);
					tabRow.ContentType = TabType;
					tabRow.ParentId = tab.ParentId;
					tabRow.CultureCode = sourcecultureCode;
					result.AddContent(tabRow, tab);


					if (tab.ParentId >= 0)
					{
						isParentFound = true;
						tabRow.Level = 1;
					}
					else
					{
						tabRow.Level = 0;
					}

					if(isnew)
						content.Content.AddContentRow(tabRow);

					TranslationState state = TranslationStateManager.Instance.GetState(tab, source, target);
					if (!state.IsEmpty)
					{
						dtoContent.LanguagePairsRow lpr = dtoContentHelper.FindLanguagePair(content, source, target);
						dtoContent.TranslationContentRow tcr = content.TranslationContent.FindByLanguagePairIdContentId
							(
								lpr.Id,
								tabRow.Id
							);

						if (tcr == null)
						{
							content.TranslationContent.AddTranslationContentRow(
							tabRow,
							lpr,
							false,
							(Int32)state.Status);
						}
						else
						{
							tcr.State = (Int32)state.Status;
						}
					}


				}
			}

			int level = 1;

			while (isParentFound)
			{
				content.Content.DefaultView.RowFilter = String.Format("Level = {0} AND ContentType = '{1}' AND CultureCode= '{2}'", level, TabType, sourcecultureCode);
				isParentFound = false;
				foreach (DataRowView dvr in content.Content.DefaultView)
				{
					dtoContent.ContentRow cr = (dtoContent.ContentRow)dvr.Row;
					TabInfo ti = (TabInfo)result.GetContent(cr);

					dtoContent.ContentRow pr = Find(content, TabType, sourcecultureCode, ti.ParentId);
					TabInfo parent = (TabInfo)result.GetContent(pr);

					if (pr.Level == level - 1)
					{
						continue;
					}

					isParentFound = true;
					cr.Level++;
				}

				level++;
			}


			IList<dtoContent.ContentRow> rmodules = new List<dtoContent.ContentRow>();


			content.Content.DefaultView.RowFilter = String.Format("ContentType = '{0}' AND CultureCode= '{1}'", TabType, sourcecultureCode);

			//Add Modules
			foreach (DataRowView dvr in content.Content.DefaultView)
			{
				dtoContent.ContentRow cr = (dtoContent.ContentRow)dvr.Row;

				TabInfo tab = (TabInfo)result.GetContent(cr);
				List<ModuleInfo> modules = GetChildModules(portalId, tab.TabID, source);

				foreach (var module in modules)
				{
					dtoContent.ContentRow moduleRow = Find(content, ModuleType, sourcecultureCode, module.ModuleID);
					bool isnew = moduleRow == null;

					if(isnew)
						moduleRow = content.Content.NewContentRow();

					moduleRow.ContentId = module.ModuleID;
					moduleRow.Title = GetContentName(module);
					moduleRow.Level = tab.Level + 1;
					moduleRow.ParentId = tab.TabID;
					moduleRow.ContentType = ModuleType;
					moduleRow.CultureCode = sourcecultureCode;
					result.AddContent(moduleRow, module);
					
					
					if(isnew)
						rmodules.Add(moduleRow);

					TranslationState state = TranslationStateManager.Instance.GetState(module, source, target);
					if (!state.IsEmpty)
					{
						dtoContent.LanguagePairsRow lpr = dtoContentHelper.FindLanguagePair(content, source, target);
						dtoContent.TranslationContentRow tcr = content.TranslationContent.FindByLanguagePairIdContentId
							(
								lpr.Id,
								moduleRow.Id
							);

						if (tcr == null)
						{
							content.TranslationContent.AddTranslationContentRow(
							moduleRow,
							lpr,
							false,
							(Int32)state.Status);
						}
						else
						{
							tcr.State = (Int32)state.Status;
						}
					}

				}
			}

			foreach (dtoContent.ContentRow cr in rmodules)
			{
				content.Content.AddContentRow(cr);
			}

			return result;
		}

		public String GetContentName(TabInfo ti)
		{
			return ti.LocalizedTabName;
		}

		public String GetContentName(ModuleInfo mi)
		{
			return mi.ModuleTitle; //String.Format("{1} ({0})", mi.DesktopModule.FriendlyName, mi.ModuleTitle);
		}

		public ContentEntity GetContent(dtoContent.ContentRow cr, int portalId)
		{
			ContentEntity result  = new ContentEntity();
			if (cr.ContentType == TabType)
			{
				TabInfo ti = TabController.GetTab(cr.ContentId, portalId, true);
				result.Id = Guid.NewGuid().ToString();
				result.CustomerIdentity = IdentityManager.GetCustomerIdentity(ti);
				result.Name = GetContentName(ti);
				result.Type = TabType;
				result.Version = VersionManager.GetVersion(ti);
				result.Content = GetSerializedContent(ti);

			}

			if (cr.ContentType == ModuleType)
			{
				ModuleInfo mi = ModuleController.GetModule(cr.ContentId, cr.ParentId, true);
				result.Id = Guid.NewGuid().ToString();
				result.CustomerIdentity = IdentityManager.GetCustomerIdentity(mi);
				result.Name = GetContentName(mi);
				result.Type = ModuleType;
				result.Version = VersionManager.GetVersion(mi);
				result.Content = ExportContent(mi);
				
			}

			return result ;
		}

		public string GetSerializedContent(TabInfo ti)
		{
			XmlDocument result = new XmlDocument();
			result.AppendChild(result.CreateElement("Content"));

			XmlElement element = result.CreateElement("PageName");
			element.InnerText = ti.TabName;
			result.DocumentElement.AppendChild(element);
			
			element = result.CreateElement("PageTitle");
			element.InnerText = ti.Title;
			result.DocumentElement.AppendChild(element);
			
			element = result.CreateElement("Description");
			element.InnerText = ti.Description;
			result.DocumentElement.AppendChild(element);
			
			element = result.CreateElement("Keywords");
			element.InnerText = ti.KeyWords;
			result.DocumentElement.AppendChild(element);

			return result.OuterXml;
		}

		public string ExportContent(ModuleInfo mi)
		{
			if (String.IsNullOrEmpty(mi.DesktopModule.BusinessControllerClass) || !mi.DesktopModule.IsPortable)
				return String.Empty;

			var objObject = Reflection.CreateObject(mi.DesktopModule.BusinessControllerClass, mi.DesktopModule.BusinessControllerClass);

			if (!(objObject is IPortable))
			{
				return string.Empty;
			}
			
			return Convert.ToString(((IPortable)objObject).ExportModule(mi.ModuleID));
		}

		public void ImportContent(int moduleId, int tabId, string contentXml, int userId)
		{
			ModuleInfo Module = new ModuleController().GetModule(moduleId, tabId, false);

			var objObject = Reflection.CreateObject(Module.DesktopModule.BusinessControllerClass, Module.DesktopModule.BusinessControllerClass);
			var xmlDoc = new XmlDocument();
			xmlDoc.LoadXml(contentXml);
			var strType = xmlDoc.DocumentElement.GetAttribute("type");
			var strVersion = xmlDoc.DocumentElement.GetAttribute("version");
			((IPortable)objObject).ImportModule(moduleId, xmlDoc.DocumentElement.InnerXml, strVersion, userId);
		}


		private static string CleanName(string name)
		{
			var strName = name;
			const string strBadChars = ". ~`!@#$%^&*()-_+={[}]|\\:;<,>?/\"'";

			int intCounter;
			for (intCounter = 0; intCounter <= strBadChars.Length - 1; intCounter++)
			{
				strName = strName.Replace(strBadChars.Substring(intCounter, 1), "");
			}
			return strName;
		}


		private TabController _tabController = null;
		private TabController TabController
		{
			get
			{
				if(_tabController == null)
				{
					_tabController = new TabController();
				}

				return _tabController;
			}
		}

		private ModuleController _moduleController = null;
		private ModuleController ModuleController
		{
			get
			{
				if (_moduleController == null)
				{
					_moduleController = new ModuleController();
				}

				return _moduleController;
			}
		}
		

	}
}